AST 转换完之后就到了 generate 阶段,genenrate 是怎么生成目标代码和 sourcemap 的呢?sourcemap 有啥作用呢?
本节就来探索一下 generate 的奥秘。
# generate
generate 是把 AST 打印成字符串,是一个从根节点递归打印的过程,对不同的 AST 节点做不同的处理,在这个过程中把抽象语法树中省略掉的一些分隔符重新加回来。
比如 while 语句 WhileStatement 就是先打印 while,然后打印一个空格和 ‘(’,然后打印 node.test 属性的节点,然后打印 ‘)’,之后打印 block 部分

比如条件表达式 ConditionExpression 就是分别打印 node.test、node.consequent、node.alternate 属性,中间插入 ? : 和空格。

通过这样的方式递归打印整个 AST,就可以生成目标代码。
@babel/generator 的 src/generators 下定义了每一种AST节点的打印方式,感兴趣的话可以去看一下。
# sourcemap
我们知道可以在 generate 的时候选择是否生成 sourcemap,那为什么要生成 sourcemap 呢?
# sourcemap 的作用
babel 对源码进行了修改,生成的目标代码可能改动很大,如果直接调试目标代码,想手动定位回源码比较难。所以需要一种自动关联源码的方式,就是 sourcemap。
我们平时用 sourcemap 主要用两个目的:
# 调试代码时定位到源码
chrome、firefox 等浏览器支持在文件末尾加上一行注释
//# sourceMappingURL=http://example.com/path/to/your/sourcemap.map
可以通过 url 的方式或者转成 base64 内联的方式来关联 sourcemap。调试工具(浏览器、vscode 等会自动解析 sourcemap,关联到源码。这样打断点、错误堆栈等都会对应到相应源码。
# 线上报错定位到源码
开发时会使用 sourcemap 来调试,但是生产可不会,要是把 sourcemap 传到生产算是大事故了。但是线上报错的时候确实也需要定位到源码,这种情况一般都是单独上传 sourcemap 到错误收集平台。
比如 sentry 就提供了一个 sentry webpack plugin 支持在打包完成后把 sourcemap 自动上传到 sentry 后台,然后把本地 sourcemap 删掉。还提供了 sentry-cli 让用户可以手动上传。
平时我们至少在这两个场景(开发时调试源码,生产时定位错误)下会用到 sourcemap。
